
#ifndef ROPUFU_MULTI_SENSOR_UNIT_TEST_TEST_DISTRIBUTION_HPP_INCLUDED
#define ROPUFU_MULTI_SENSOR_UNIT_TEST_TEST_DISTRIBUTION_HPP_INCLUDED

#include <aftermath/probability/dist_normal.hpp>
#include <aftermath/random/sampler_normal.hpp>
//#include <aftermath/random/ziggurat_normal_1024_uint32.hpp>
//#include <aftermath/random/ziggurat_normal_1024_lcg31.hpp>

#include <chrono>
#include <cstdint>
#include <iostream>
#include <random>
#include <string>
#include <vector>

namespace ropufu
{
    namespace unit_test
    {
        // Chi-squared distribution test for normal distribution.
        bool test_distribution_normal()
        {
            std::vector<double> p_value_twenty_by_df = { 1.64, 3.22, 4.64, 5.99, 7.29, 8.56, 9.80, 11.03, 12.24, 13.44 };

            bool is_success = true;
            const std::size_t degrees_of_freedom = 10;
            double p_ref = 0.2;
            double chi_ref = p_value_twenty_by_df[degrees_of_freedom - 1];

            std::normal_distribution<double> dist0(0.0, 1.0);
            std::normal_distribution<double> samp0(dist0);

            aftermath::probability::dist_normal dist1(0.0, 1.0);
            aftermath::random::sampler_normal_from_engine<1024, std::default_random_engine>::type samp1(dist1);

            //typedef std::default_random_engine engine_type;
            typedef std::default_random_engine engine_type;
            std::uint32_t seed = static_cast<std::uint32_t>(std::chrono::high_resolution_clock::now().time_since_epoch().count());
            engine_type engine(seed);

            double p0 = 0.0;
            double p1 = 0.0;

            std::size_t m = 1000000UL;
            for (std::size_t j = 0; j < m; j++)
            {
                double chi0 = 0.0;
                double chi1 = 0.0;

                for (std::size_t i = 0; i < degrees_of_freedom; i++)
                {
                    double z0 = samp0(engine);
                    double z1 = samp1(engine);
                    chi0 += z0 * z0;
                    chi1 += z1 * z1;
                }
                if (chi0 > chi_ref) p0++;
                if (chi1 > chi_ref) p1++;
            }
            p0 /= m;
            p1 /= m;

            std::cout << "Built-in sample: " << p0 << std::endl;
            std::cout << "Aftermath sample: " << p1 << std::endl;
            std::cout << "Reference: " << p_ref << std::endl;

            return is_success;
        }
    }
}

#endif // ROPUFU_MULTI_SENSOR_UNIT_TEST_TEST_DISTRIBUTION_HPP_INCLUDED
